home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Speccy ClassiX 1998
/
Speccy ClassiX 98.iso
/
amiga_system
/
the_aminet
/
dev
/
gcc
/
ixemulsrc.lha
/
ixemul-41.4
/
library
/
convert_dir.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-28
|
6KB
|
202 lines
/*
* This file is part of ixemul.library for the Amiga.
* Copyright (C) 1991, 1992 Markus M. Wild
* Portions Copyright (C) 1994 Rafael W. Luebbert
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: convert_dir.c,v 1.4 1994/06/19 15:09:22 rluebbert Exp $
*
* $Log: convert_dir.c,v $
* Revision 1.4 1994/06/19 15:09:22 rluebbert
* *** empty log message ***
*
* Revision 1.2 1992/07/28 00:42:36 mwild
* fix signals, fix memory leak, fix possible never unlocked lock
*
* Revision 1.1 1992/05/14 19:55:40 mwild
* Initial revision
*
*/
#define KERNEL
#include "ixemul.h"
#include "kprintf.h"
/* don't need to use the async port, no more than 1 task will be in here
* at a time and use our packet */
#define __srwport (u.u_sync_mp)
extern int __mread (), __mclose ();
extern void *kmalloc (size_t), *krealloc (void *, size_t);
#if __GNUC__ != 2
#define alloca __builtin_alloca
#endif
#define BUFINCR 512
/* we're writing records that look like this to the `file' */
struct file_dir {
long fd_key;
long fd_namelen; /* padded to even size, thus perhaps zero padded */
char fd_name[0]; /* fd_namelen bytes of filename */
};
/*
* Convert a directory into a DTYPE_MEM file.
*
* NOTE: function assumes:
* o f is allocated and locked, it's packet is initialized
* o name is an existing directory (S_IFDIR from a previous stat)
* o signals are blocked (important! convert_dir() doesn't block them!)
*/
int
convert_dir (struct file *f, char *name, int omask)
{
BPTR lock;
u_char *buf, *bp, *bend;
int buf_size;
struct FileInfoBlock *fib;
struct file_dir *fd;
int len, res, err, rc0;
fib = alloca (sizeof (*fib) + 2);
fib = LONG_ALIGN (fib);
res = 0;
if ((lock = __lock (name, ACCESS_READ)) > 0)
{
buf = kmalloc (BUFINCR);
buf_size = BUFINCR;
bp = buf;
bend = buf + buf_size;
/* make sure we got that memory */
if (! buf)
{
err = ENOMEM;
res = -1;
goto do_return;
}
rc0 = Examine (lock, fib);
/* put two dummy entries here.. some BSD code relies on the fact that
* it can safely skip the first two `.' and `..' entries ;-)) */
fd = (struct file_dir *) bp;
fd->fd_key = 1;
fd->fd_namelen = 2;
fd->fd_name[0] = '.'; fd->fd_name[1] = 0;
bp += fd->fd_namelen + sizeof (struct file_dir);
fd = (struct file_dir *) bp;
fd->fd_key = 2;
fd->fd_namelen = 2;
fd->fd_name[0] = '.'; fd->fd_name[1] = '.';
bp += fd->fd_namelen + sizeof (struct file_dir);
/* don't include the dir-information into the file, *ix doesn't either. */
if (rc0 == -1)
for (;;)
{
/* allow for a clean abort out of a very long directory scan */
if (u.p_sig & ~omask)
{
/* if a signal is pending that was not blocked before entry to
* open(), break here and return with EINTR */
res = -1;
err = EINTR;
kfree (buf);
goto do_return;
}
rc0 = ExNext (lock, fib);
if (rc0 != -1) break;
len = strlen (fib->fib_FileName);
if ((bp + (len + 2 + sizeof (struct file_dir))) >= bend)
{
u_char *tmp;
tmp = krealloc (buf, buf_size + BUFINCR);
if (! tmp)
{
ix_panic ("ixemul.library: out of memory!");
res = -1;
kfree (buf);
err = ENOMEM;
goto do_return;
}
buf_size += BUFINCR;
bp = tmp + (bp-buf);
buf = tmp;
bend = tmp + buf_size;
}
fd = (struct file_dir *) bp;
fd->fd_key = fib->fib_DiskKey;
fd->fd_namelen = len;
/* watch out for mc68000: don't let bp ever get odd ! */
if (fd->fd_namelen & 1)
/* in that case zero pad the name */
fd->fd_name[fd->fd_namelen++] = 0;
bcopy (fib->fib_FileName, fd->fd_name, len);
bp += fd->fd_namelen + sizeof (struct file_dir);
#ifdef DEBUG
if (bp >= bend || & fd->fd_name[len] >= bend)
{
KPRINTF (("cd: OVERFLOW! bp = $%lx, bend = $%lx, len = $%lx, &fd->fd_name[len] = $%lx\n",
bp, bend, len, & fd->fd_name[len]));
}
#endif
}
/* fine.. fill out the memory file object */
f->f_type = DTYPE_MEM;
f->f_mf.mf_offset = 0;
f->f_mf.mf_buffer = buf;
f->f_read = __mread;
f->f_close = __mclose;
f->f_ioctl = 0;
f->f_select = 0;
f->f_stb.st_size = bp-buf;
/* NOTE: the rest of the stb should be ok from the previous stat() in
* open() */
}
else
{
errno = ENOENT;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return -1;
}
/* NOTE: granted, this is a bit spaghetti here.. the else above guarantees that
we won't unlock a lock we never got. So it's safe to unconditionally
unlock at the end. */
do_return:
__unlock (lock);
errno = err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return res;
}